package com.ludomancy.gamelib;

/*
 *   PlayerTest.
 * 
 *   JavaZOOM : vorbisspi@javazoom.net
 *              http://www.javazoom.net
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as published
 *   by the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Library General Public License for more details.
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */
import java.io.IOException;
import java.net.URL;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

/**
 * Simple player (based on Vorbis SPI) unit test. It takes around 3%-5% of CPU
 * and 10MB RAM under Win2K/P4/2.4GHz/JDK1.4.1 It takes around 4% of CPU and
 * 10MB RAM under Win2K/Athlon/1GHz/JDK1.3.1
 */
public class Music
{
	private URL url;
	private boolean stop = false;
	private boolean loop = false;
	
	private AudioFormat decodedFormat;
	private AudioInputStream din;
	private AudioInputStream in;
	private SourceDataLine line;
	
	public Music(String path)
	{
		url = GameApplet.gameAppletInstance.getClass().getResource("/"+path);
		
		try
		{
			resetInputStreams();
			line = getLine(decodedFormat);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
	
	public void loop()
	{
		if(Sound.soundActivated)
		{
			loop = true;
			play();
		}
	}
	
	public void play()
	{
		new Thread()
		{
			public void run()
			{
				internalPlay();
			}
		}.start();
	}
	
	public void stop()
	{
		stop = true;
	}
	
	private void internalPlay()
	{
		try
		{
			byte[] data = new byte[4096];
			if (line != null)
			{
				// Start
				line.start();
				int nBytesRead = 0;
				while (nBytesRead != -1 && !stop)
				{
					nBytesRead = din.read(data, 0, data.length);
					if (nBytesRead != -1)
					{
						line.write(data, 0, nBytesRead);
					}
					else
					{
						if(loop)
						{
							din.close();
							resetInputStreams();
							nBytesRead = 0;
						}
					}
				}
				// Stop
				line.drain();
				line.stop();
				line.close();
				din.close();
				in.close();
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	private void resetInputStreams()
	{
		// Get AudioInputStream from given file.
		try
		{
			in = AudioSystem.getAudioInputStream(url);
			if (in != null)
			{
				AudioFormat baseFormat = in.getFormat();
				decodedFormat = new AudioFormat(
						AudioFormat.Encoding.PCM_SIGNED, baseFormat
								.getSampleRate(), 16, baseFormat.getChannels(),
						baseFormat.getChannels() * 2, baseFormat
								.getSampleRate(), false);
				// Get AudioInputStream that will be decoded by underlying
				// VorbisSPI
				din = AudioSystem.getAudioInputStream(decodedFormat, in);
			}
		} 
		catch (UnsupportedAudioFileException e)
		{
			e.printStackTrace();
		} 
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	private SourceDataLine getLine(AudioFormat audioFormat) throws LineUnavailableException
	{
		SourceDataLine res = null;
		DataLine.Info info = new DataLine.Info(SourceDataLine.class,
				audioFormat);
		res = (SourceDataLine) AudioSystem.getLine(info);
		res.open(audioFormat);
		return res;
	}
}
